<?php
/**
 * ============================================================================
 * Author: Abing
 * Date: 17-3-22
 * 联系QQ:501443501
 * ============================================================================
 */
require __DIR__.'/../lib/user.php';
require __DIR__.'/../lib/article.php';
$pdo = require __DIR__.'/../lib/db.php';
class Restful{
    /**
     * @var User
     */
    private $_user;
    /**
     * @var Article
     */
    private $_article;
    /**
     * 请求方法
     * @var string
     */
    private $_requestMethod;
    /**
     * 请求资源名称
     * @var string
     */
    private $_resourceName;
    /**
     * 请求的资源ID
     * @var
     */
    private $_id;
    /**
     * 允许请求的资源列表
     * @var array
     */
    private $_allowResources = ['users','articles'];
    /**
     * 允许请求的http方法
     * @var array
     */
    private $_allowRequestMethods = ['GET','POST','PUT','DELETE','OPTIONS'];
    /**
     * 常用的状态码
     * @var array
     */
    private $_stausCodes = [
        200=>'ok',
        204=>'No Content',
        400=>'Bad Request',
        401=>'Unauthorized',
        403=>'Forbidden',
        404=>'Not Fount',
        405=>'Method Not Allowed',
        500=>'Server Internal Error'
    ];
    /**
     * 构造函数
     * @param User $_user
     * @param Article $_article
     */
    public function __construct(User $_user,Article $_article){
        $this->_user = $_user;
        $this->_article = $_article;
    }
    public function run(){
        try{
        $this->_setupRequestMethod();
        $this->_setupResource();
        if($this->_resourceName == 'users'){
            return $this->_json($this->_handleUser());
        }else{
            return $this->_json($this->_handleArticle());
        }
        }catch (Exception $e){
            $this->_json(['error'=>$e->getMessage()],$e->getCode());
        }
    }

    /**
     * 初始化请求方法
     */
    private function _setupRequestMethod(){
        $this->_requestMethod =$_SERVER['REQUEST_METHOD'];
        if(!in_array($this->_requestMethod,$this->_allowRequestMethods)){
            throw new Exception('请求方法不被允许',405);
        }
    }

    /**
     * 初始化请求资源
     */
    private function _setupResource(){
        $path = $_SERVER['REQUEST_URI'];
        $params = explode('/',$path);
        $this->_resourceName = $params[2];
        if(!in_array($this->_resourceName,$this->_allowResources)){
            throw new Exception('请求资源不被允许',400);
        }
        if(!empty($params[3])){
            $this->_id = $params[3];
        }
    }

    /**
     * 输出JSON
     * @param $array
     * @param int $code
     */
    private function _json($array,$code = 0){
        if($array === null&&$code===0){
            $code =204;
        }
        if($array!==null&&$code===0){
            $code = 200;
        }
        header("HTTP/1.1".$code." ".$this->_stausCodes[$code]);
        header('Content-Type:application/json;charset=utf-8');
        if($array!==null){
          echo json_encode($array,JSON_UNESCAPED_UNICODE);
        }
        exit();
    }

    /**
     * 请求用户资源
     */
    private function _handleUser(){
        if($this->_requestMethod != 'POST'){
            throw new Exception('请求不被允许',405);
        }
        $body = $this->_getBodyParams();
        if(empty($body['username'])){
            throw new Exception('用户名不能为空',400);
        }
        if(empty($body['password'])){
            throw new Exception('密码不能为空',400);
        }
        return $this->_user->register($body['username'],$body['password']);
    }

    /**
     * 请求文章资源
     */
    private function _handleArticle(){
        switch($this->_requestMethod){
            case 'POST':
                return $this->_handleArticleCreate();
            case 'PUT':
                return $this->_handleArticleEdit();
            case 'DELETE':
                return $this->_handleArticleDelete();
            case 'GET':
                if(empty($this->_id)){
                    return $this->_handleArticleList();
                }else{
                    return $this->_handleArticleView();
                }
                default:
                throw new Exception('请求方法不被允许',405);

        }
    }

    /**
     * 获取请求参数
     * @return mixed
     * @throws Exception
     */
    private function _getBodyParams(){
        $raw = file_get_contents('php://input');
        if(empty($raw)){
            throw new Exception('请求参数错误',400);
        }
        return json_decode($raw,true);
    }

    /**
     * 创建文章
     */
    private function _handleArticleCreate(){
        $body = $this->_getBodyParams();
        if(empty($body['title'])){
            throw new Exception('文章标题不能为空',400);
        }
        if(empty($body['content'])){
            throw new Exception('文章内容不能为空',400);
        }
        $user = $this->_userLogin('admin','admin');
       //$user = $this->_userLogin($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']);
        try{
            $article = $this->_article->create($body['title'],$body['content'],$user['user_id']);
            return $article;
        }catch (Exception $e){
            if(!in_array($e->getCode(),[
                ErrorCode::ARTICLE_TITLE_EMPTY,
                ErrorCode::ACTICLE_CONTENT_EMPTY
            ])){
                throw new Exception($e->getMessage(),400);
            }
            throw new Exception($e->getMessage(),500);
        }
    }

    /**
     * 文章编辑
     */
    private function _handleArticleEdit(){
        $user = $this->_userLogin('admin','admin');
        try{
            $article = $this->_article->view($this->_id);
            if($article['user_id']!=$user['user_id']){
                throw new Exception('您无权限编辑此文章',403);
            }
            $body = $this->_getBodyParams();
            $title = empty($body['title'])?$article['title']:$body['title'];
            $content = empty($body['content'])?$article['content']:$body['content'];
            if($title==$article['title']&&$content==$article['content']){
                return $article;
            }

            return $this->_article->edit($title,$content,$user['user_id'],$article['article_id']);
        }catch (Exception $e){
            if($e->getCode()==ErrorCode::ACTICLE_EMPTY){
                throw new Exception($e->getMessage(),404);
            }else{
                throw new Exception($e->getMessage(),400);
            }
        }
    }

    private function _handleArticleDelete(){
        $user = $this->_userLogin('admin','admin');
        try{
            $article = $this->_article->view($this->_id);
            if($article['user_id']!=$user['user_id']){
                throw new Exception('您无权限编辑',403);
            }
            $this->_article->delete($user['user_id'],$article['article_id']);
            return null;
        }catch (Exception $e){
            if($e->getCode()<100){
                if($e->getCode()==ErrorCode::ACTICLE_EMPTY){
                    throw new Exception($e->getMessage(),404);
                }else{
                    throw new Exception($e->getMessage(),400);
                }
            }else{
                throw $e;
            }
        }
    }

    /**
     * 文章列表
     */
    private function _handleArticleList(){
        $user = $this->_userLogin('admin','admin');
        $page = isset($_GET['page'])?$_GET['page']:1;
        $size = isset($_GET['size'])?$_GET['size']:10;
        if($size>100){
            throw new Exception('分页大小最大100',400);
        }
        return $this->_article->lists($user['user_id'],$page,$size);
    }

    /**
     * 查看文章
     */
    private function _handleArticleView(){
        try{
            return $this->_article->view($this->_id);
        }catch (Exception $e){
            if($e->getCode() == ErrorCode::ACTICLE_EMPTY){
                throw new Exception($e->getMessage(),400);
            }else{
                throw new Exception($e->getMessage(),500);
            }
        }
    }

    /**
     * 用户登录
     * @param $PHP_AUTH_USER
     * @param $PHP_AUTH_PW
     * @throws Exception
     * @return mixed
     */
    private function _userLogin($PHP_AUTH_USER, $PHP_AUTH_PW){
        try{
            return $this->_user->login($PHP_AUTH_USER, $PHP_AUTH_PW);
        }catch (Exception $e){
            if(in_array($e->getCode(),[
                ErrorCode::USERNAME_EMPTY,
                ErrorCode::PASSWORD_EMPTY,
                ErrorCode::USERNAME_ORPASSWORD_WORN
            ])){
                throw new Exception($e->getMessage(),400);
            }
            throw new Exception($e->getMessage(),500);
        }
    }

}
$article = new Article($pdo);
$user = new User($pdo);

$restful = new Restful($user,$article);
$restful->run();